//
//  RefreshControl.swift
//  Practice
//
//  Created by miaozhihui on 2017/3/6.
//  Copyright © 2017年 DeKuTree. All rights reserved.
//

import UIKit

/// 刷新状态切换的临界点
private let refreshOffset: CGFloat = 126

/// 刷新状态
///
/// - Normal: 普通状态
/// - Pulling: 超过临界点，如果放手，开始刷新
/// - Refreshing: 正在刷新
enum RefreshState {
    case Normal
    case Pulling
    case Refreshing
}

/// 刷新控件 - 负责刷新相关的逻辑处理
class RefreshControl: UIControl {
    
    private weak var scrollView: UIScrollView?
    
    /// 刷新视图
    fileprivate lazy var refreshView: RefreshView = RefreshView.refreshView()
    
    /// 构造函数
    init() {
        super.init(frame: CGRect())
        setupUI()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setupUI()
    }
    
    override func willMove(toSuperview newSuperview: UIView?) {
        super.willMove(toSuperview: newSuperview)
        guard let sv = newSuperview as? UIScrollView else {
            return
        }
        scrollView = sv
        scrollView?.addObserver(self, forKeyPath: "contentOffset", options: [], context: nil)
    }
    
    override func removeFromSuperview() {
        
        // superView 存在
        superview?.removeObserver(self, forKeyPath: "contentOffset")
        
        super.removeFromSuperview()
        
    }
    
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        guard let sv = scrollView else {
            return
        }
        let height = -(sv.contentInset.top + sv.contentOffset.y)
        
        if height < 0 {
            return
        }
        
        frame = CGRect(x: 0, y: -height, width: sv.bounds.width, height: height)
        print(height)
        
//        // 传递父视图高度到子视图
//        refreshView.parentViewHeight = height
        
        // 判断临界点
        if sv.isDragging { // 正在拖拽
            if height > refreshOffset && (refreshView.refreshState == .Normal) { // 大于临界点，并且刷新状态是Normal时需要改变状态为Pulling
                refreshView.refreshState = .Pulling
                print("放手刷新")
            } else if height <= refreshOffset && refreshView.refreshState == .Pulling { // 小于临界点，并且刷新状态是Pulling时需要改变状态为Normal
                refreshView.refreshState = .Normal
                print("再使劲...")
            }
            // 传递父视图高度到子视图
            refreshView.parentViewHeight = height
        } else { // 放手
            
            if refreshView.refreshState == .Pulling { // 超过临界点
                print("准备开始刷新")
                
                beginRefreshing()
                sendActions(for: .valueChanged)
//                // 刷新结束之后，将状态修改为Normal，才能继续响应刷新
//                refreshView.refreshState = .Refreshing
//                
//                // 让整个刷新视图能够显示出来
//                // 解决方法: 修改表格的contentInset
//                var inset = sv.contentInset
//                inset.top += refreshOffset
//                sv.contentInset = inset
            }
        }
        
    }
    
    /// 开始刷新
    func beginRefreshing() {
        print("开始刷新")
        
        // 判断父视图
        guard let sv = scrollView else { return  }
        
        // 如果正在刷新，返回
        if refreshView.refreshState == .Refreshing {
            return
        }
        
        // 设置刷新视图状态
        refreshView.refreshState = .Refreshing
        
        // 调整间距
        var inset = sv.contentInset
        inset.top += refreshOffset
        sv.contentInset = inset
        
        refreshView.parentViewHeight = refreshOffset
    }
    
    /// 结束刷新
    func endRefreshing() {
        print("结束刷新")
        
        guard let sv = scrollView else { return  }
        
        // 如果不是正在刷新，直接返回
        if refreshView.refreshState != .Refreshing {
            return
        }
        DispatchQueue.main.asyncAfter(deadline: .now()+5) { 
            // 恢复刷新视图的状态
            self.refreshView.refreshState = .Normal
            // 恢复表格视图的 contentInset
            var inset = sv.contentInset
            inset.top -= refreshOffset
            sv.contentInset = inset
        }
    }
}

extension RefreshControl {
    
    fileprivate func setupUI() {
        
        backgroundColor = superview?.backgroundColor
        
        // 设置超出边界不显示
//        clipsToBounds = true
        
        // 添加刷新视图
        addSubview(refreshView)
        
        // 自动布局 - 设置 xib 控件的自动布局，需要制定宽高约束
        refreshView.translatesAutoresizingMaskIntoConstraints = false
        
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0))
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0))
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: refreshView.bounds.width))
        addConstraint(NSLayoutConstraint(item: refreshView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: refreshView.bounds.height))
    }
}
